﻿using DLL.NET50.DB.MS.AdviceAndDrug;
using DLL.Net60.MotionCtrl.ControlBase;
using DLL.NET60.DB.MS.Entity.DTO;
using DLL.NET60.MotionCtrl.Entitys;
using DLL.NET70.Infrastructure.EventAggregator;
using DLL.NetStandard.FlushRobot.MS.Entity.Param;
using DLL.Standard.Infrastructure.Entity;
using DLL.Standard.Infrastructure.Log;

using Prism.Events;
using Prism.Services.Dialogs;

using System;
using System.Collections.ObjectModel;
using System.Threading;
using System.Windows;

namespace DLL.FlushRobot.MS.Run
{
    public interface IMS_HP_RunBase
    {
        public CMS_AdviceAndDrugs advices { get; set; }//传递过来的医嘱
        public CMultyInjectors mInjectors { get; set; }
        public bool NeedleInBottle { get; set; }
    }

    public class CMS_HP_RunBase : IMS_HP_RunBase
    {
        #region property

        private CMS_AdviceAndDrugs _advices = new CMS_AdviceAndDrugs();//传递过来的医嘱

        public CMS_AdviceAndDrugs advices
        {
            get { return _advices; }
            set { _advices = value; }
        }

        public CMultyInjectors _mInjectors;

        public CMultyInjectors mInjectors
        {
            get { return _mInjectors; }
            set { _mInjectors = value; }
        }

        public bool _NeedleInBottle = false;

        public bool NeedleInBottle
        {
            get { return _NeedleInBottle; }
            set { _NeedleInBottle = value; }
        }

        #endregion property

        private IDialogService _dialogService;
        private IEventAggregator _eventAggregator;

        public CMS_HP_RunBase(IDialogService dialogService, IEventAggregator eventAggregator)
        {
            _dialogService = dialogService;
            _eventAggregator = eventAggregator;
        }

        #region 变量

        public static int _X = 0;
        public static int _Y = 1;
        public static int _Z = 2;
        public static int heightDiffluent = 0;//最容易溶解
        public static int middleDidffluent = 1;//中等易容
        public static int lowDiffluent = 2;//轻度易容
        public static int lowInsoluble = 3;//轻度难容
        public static int middleInsoluble = 4;//轻度难容
        public static int highInsoluble = 5;//轻度难容

        public static int heightPostivePressure = 0;//高正压
        public static int middlePostivePressure = 1;//中正压
        public static int lowPostivePressure = 2;//轻正压
        public static int normalPressure = 3;//常压
        public static int lowNegativePressure = 4;//轻度负压
        public static int middleNegativePressure = 5;//中度负压
        public static int heightNegativePressure = 6;//重度负压

        public static int noBubbles = 0;
        public static int LowBubbles = 1;
        public static int middleBubbles = 2;
        public static int heightBubbles = 3;

        public const int MaxZAxisCount = 10;
        public const int MaxRowPointCount = 8;
        public const int MaxSubRowPointCount = 5;
        public const int MaxColPointCount = 8;
        public int StationColNum = 4;
        public int StationRowNum = 5;

        //private double AdditionalVolume = 1.5;//每次多抽的体积，到下一瓶要排出这个空气
        //public long ret = 0;

        //public string runState = "";
        //public int StateLevel = 0;

        public CMultyLoopStations MulLoopStations = new CMultyLoopStations();//最终解析出来的，可以进行配药的类
        public COneLoopStations OneLoopStations = new COneLoopStations();
        public IMotionCtrlBase nMotionCtrl;
        public CMS_DeviceConfigParam DeviceConfig = new CMS_DeviceConfigParam();//设备参数
        public CMS_WorkPointParam WorkPoint = new CMS_WorkPointParam();//加工点位
        public CMS_WorkConfigParam WorkConfig = new CMS_WorkConfigParam();

        //
        public ObservableCollection<CAxisSpeed> axisesSpeed;

        #endregion 变量

        #region base fun

        public void SendLogMessage(string _message, LogLevel level = LogLevel.Debug)
        {
            CLogMessage lm = new CLogMessage();
            lm.Message = _message;
            lm.Level = (int)level;
            _eventAggregator.GetEvent<CLogMessageEvent>().Publish(lm);
        }

        public void LogMessage(string _message, LogLevel level = LogLevel.Debug)
        {
            SendLogMessage(_message);
        }

        public void SetRunState(string messsage, LogLevel level = LogLevel.Debug)
        {
            LogMessage(messsage, level);
        }

        public double MLTomm(double iMl)
        {
            double pos = 0;
            pos = iMl * DeviceConfig.MLToMM;
            return pos;
        }

        private double GetMPos(int AxisID)
        {
            double mPos = nMotionCtrl.AbsDestPos_Pulse[AxisID] / nMotionCtrl.motionParam.axis.runParam.axisesRunParam[AxisID].PulsePerMili;
            return mPos;
        }

        public int WaitEmgOpen()
        {
            long ret = 0;
            bool emg = false;
            ret = nMotionCtrl.GetEmgState(ref emg);
            if (0 == ret)
            {
                return 0;
            }
            while (!emg)
            {
                //MessageBox.Show("急停按钮被按下，无法继续配药，请打开急停按钮！");
                string str = "急停按钮被按下，无法继续配药，请打开急停按钮！";
                Application.Current.Dispatcher.Invoke(
                (Action)delegate ()
                {
                    _dialogService.ShowDialog("WarningDialog", new DialogParameters($"message={str}"), null);
                });
                ret = nMotionCtrl.GetEmgState(ref emg);
                if (0 == ret)
                {
                    return 0;
                }
            }
            return 1;
        }

        public double[] VolumeSub(double[] barray, double[] jarray)
        {
            double[] sub = new double[MaxColPointCount];
            for (int i = 0; i < StationColNum; i++)
            {
                sub[i] = barray[i] - jarray[i];
                if (sub[i] < 0)
                {
                    sub[i] = 0;
                }
            }
            return sub;
        }

        public double[] VolumeAdd(double[] barray, double[] jarray)
        {
            double[] sub = new double[MaxColPointCount];
            for (int i = 0; i < StationColNum; i++)
            {
                sub[i] = barray[i] + jarray[i];
                if (sub[i] > DeviceConfig.InjectorMaxML)
                {
                    sub[i] = DeviceConfig.InjectorMaxML;
                }
            }
            return sub;
        }

        public double GetMaxValue(double[] all)
        {
            int count = all.Length;
            double a = 0;
            for (int i = 0; i < count; i++)
            {
                if (all[i] > a)
                {
                    a = all[i];
                }
            }
            return a;
        }

        public int GetMaxValue(int[] all)
        {
            int count = all.Length;
            int a = 0;
            for (int i = 0; i < count; i++)
            {
                if (all[i] > a)
                {
                    a = all[i];
                }
            }
            return a;
        }

        public double GetMinValue(double[] all)
        {
            int count = all.Length;
            double a = all[0];
            for (int i = 0; i < count; i++)
            {
                if (all[i] < a)
                {
                    a = all[i];
                }
            }
            return a;
        }

        public string ArrayToString<T>(T[] array)
        {
            string str = "";
            for (int i = 0; i < array.Length; i++)
            {
                str += array[i].ToString() + "-";
            }
            return str;
        }

        public int GetMinValue(int[] all)
        {
            int count = all.Length;
            int a = GetNotZeroValue(all);
            for (int i = 0; i < count; i++)
            {
                if (all[i] != 0)
                {
                    if (all[i] < a)
                    {
                        a = all[i];
                    }
                }
            }
            return a;
        }

        public int GetNotZeroValue(int[] ivalue)
        {
            int count = ivalue.Length;

            for (int i = 0; i < count; i++)
            {
                if (ivalue[i] > 0)
                {
                    return ivalue[i];
                }
            }
            return 0;
        }

        public int[] GetValidValue(int[] iValue, int[] validCol)
        {
            for (int col = 0; col < iValue.Length; col++)
            {
                if (validCol[col] == 0)
                {
                    iValue[col] = 0;
                }
            }
            return iValue;
        }

        public double[] GetValidValue(double[] iValue, int[] validCol)
        {
            for (int col = 0; col < iValue.Length; col++)
            {
                if (validCol[col] == 0)
                {
                    iValue[col] = 0;
                }
            }
            return iValue;
        }

        public int[] GetCanUsedFlag(int[] values, int maxValue)
        {
            int leng = values.Length;
            int[] flags = new int[MaxColPointCount];
            for (int col = 0; col < leng; col++)
            {
                if (values[col] >= maxValue)
                {
                    flags[col] = 1;
                }
                else
                {
                    flags[col] = 0;
                }
            }
            return flags;
        }

        public double[] ValueToArray(double value)
        {
            double[] arraryValues = new double[MaxColPointCount];
            for (int i = 0; i < StationColNum; i++)
            {
                arraryValues[i] = value;
            }
            return arraryValues;
        }

        public int[] ValueToArray(int value)
        {
            int[] arraryValues = new int[MaxColPointCount];
            for (int i = 0; i < StationColNum; i++)
            {
                arraryValues[i] = value;
            }
            return arraryValues;
        }

        public bool AllValueIsZero(double[] vas)
        {
            for (int i = 0; i < StationColNum; i++)
            {
                if (Math.Abs(vas[i]) > 0)
                {
                    return false;
                }
            }
            return true;
        }

        public bool AllValueIsZero(int[] vas)
        {
            for (int i = 0; i < StationColNum; i++)
            {
                if (vas[i] > 0)
                {
                    return false;
                }
            }
            return true;
        }

        public bool AllValueIsNotZero(int[] vas)
        {
            for (int i = 0; i < StationColNum; i++)
            {
                if (vas[i] == 0)
                {
                    return false;
                }
            }
            return true;
        }

        #region common function

        //获取冲刷用时
        public double GetMaxFlushInUsedTime(COneRowStation oneRow, int dmLoopIndex, int[] inValidCol, double[] inVolume)
        {
            int[] flushInSpeed = oneRow.GetFlushInSpeed(dmLoopIndex);
            int[] validCol = oneRow.ANDFlag(inValidCol);
            double maxTime = GetMaxUsedTime(inVolume, flushInSpeed, validCol);
            return maxTime;
        }

        public double GetMaxPullOutAdditionAirUsedTime(COneRowStation oneRow, int loopIndex, int[] inValidCol, double[] inVolume)
        {
            int[] FlushOutSlowSpeed = oneRow.GetFlushOutSlowSpeed(loopIndex);
            int[] validCol = oneRow.ANDFlag(inValidCol);
            double maxTime = GetMaxUsedTime(inVolume, FlushOutSlowSpeed, validCol);
            return maxTime;
        }

        private double[] GetUsedTime(double[] inVolume, int[] speed, int[] iValidCol)
        {
            double[] timeValues = new double[MaxColPointCount];
            double selectedVolume = 0;
            int selectedColID = 0;
            double selectedTime = 0;
            double[] speedValues = GetAllZAixsSpeedByPercent(speed);
            for (int col = 0; col < StationColNum; col++)
            {
                if (iValidCol[col] == 1)
                {
                    timeValues[col] = (inVolume[col] * DeviceConfig.MLToMM) / speedValues[col];
                    if (timeValues[col] > selectedTime)
                    {
                        selectedVolume = inVolume[col];
                        selectedTime = timeValues[col];
                        selectedColID = col;
                    }
                }
                else
                {
                    timeValues[col] = 0;
                }
            }

            return timeValues;
        }

        private double GetMaxUsedTime(double[] inVolume, int[] speed, int[] iValidCol)
        {
            double[] timeValues = GetUsedTime(inVolume, speed, iValidCol);
            double maxTime = GetMaxValue(timeValues);
            return maxTime;
        }

        #endregion common function

        #endregion base fun

        #region 设置速度函数

        public double[] GetAllZAixsSpeedByPercent(int[] percent)
        {
            double[] ASpeed = new double[MaxColPointCount];
            for (int axisID = 2; axisID < nMotionCtrl.motionParam.motionCardParam.UsedAxisCount; axisID++)
            {
                int colID = axisID - _Z;
                double speed = SpeedPercentToMM(axisID, percent[colID]);
                ASpeed[colID] = speed;
            }
            return ASpeed;
        }

        private double SpeedPercentToMM(int axisID, int percent)
        {
            double acSpeed = 0;
            double respeed = 0;
            if ((percent > 0) && (percent <= 100))
            {
                respeed = percent;
            }
            else
            {
                respeed = 50;
            }
            double speed = nMotionCtrl.GetMaxSpeedmm(axisID);
            acSpeed = speed * (respeed / 100.0);
            return acSpeed;
        }

        public double SetAxisSpeedByPercent(int AxsiID, int percent)
        {
            double speed = SpeedPercentToMM(AxsiID, percent);
            nMotionCtrl.SetAxisSpeed(AxsiID, speed);
            return speed;
        }

        public double[] SetAllZAxisSpeedByPercent(int[] percent)
        {
            double[] speed = GetAllZAixsSpeedByPercent(percent);
            for (int axisID = 2; axisID < nMotionCtrl.motionParam.motionCardParam.UsedAxisCount; axisID++)
            {
                nMotionCtrl.SetAxisSpeed(axisID, speed[axisID - _Z]);
            }
            return speed;
        }

        #endregion 设置速度函数

        #region 单抽运动

        #region X轴单周运动

        public long XMoveToDstPos(double pos)
        {
            long ret = 0;
            ret = nMotionCtrl.AbsMove(_X, pos);
            if (0 == ret)
            {
                return 0;
            }
            ret = nMotionCtrl.WaitForStop(_X);
            if (0 == ret) { return 0; }

            return 1;
        }

        public long Bottle_XMoveToFlushPos(COneRowStation oneRow)
        {
            nMotionCtrl.WorkPointID = oneRow.RowID + 1;

            return XBottleMoveToPuctruePos(oneRow.XPos);
        }

        public long XBottleMoveToPuctruePos(double posX)
        {
            long ret = 0;
            bool posOK = false;
            while (!posOK)
            {
                //移动小药所在的行到针管的正上方
                ret = XMoveToDstPos(posX);
                if (0 == ret) { return 0; }
                //添加到位检测
                if ((WorkConfig.EnableDetection == 1) && (nMotionCtrl.motionParam.nIOSet.iPausePort > 0))
                {
                    int v = 0;
                    ret = nMotionCtrl.ReadChannelInput(nMotionCtrl.motionParam.nIOSet.iPausePort, ref v);
                    if (1 == ret)
                    {
                        if (v == 1)
                        {
                            ButtonResult mbr = ButtonResult.Yes;//
                            Application.Current.Dispatcher.Invoke(
                            (Action)delegate ()
                            {
                                _dialogService.ShowDialog("AlertDialog", new DialogParameters($"message={"X轴移动到目标位置，没有感应到传感器，是否需要回零？"}"), r =>
                                {
                                    mbr = r.Result;
                                });
                            });
                            if (mbr == ButtonResult.Yes)
                            {
                                YMoveToDestPos(0);
                                nMotionCtrl.sAxisID = 0;
                                nMotionCtrl.SingleAxisHome();
                                posOK = false;
                            }
                            else
                            {
                                return 0;
                            }
                        }
                        else
                        {
                            posOK = true;
                        }
                    }
                    else
                    {
                        return 0;
                    }
                }
                else
                {
                    posOK = true;
                }
            }
            return 1;
        }

        public long XSolventMoveToExtractPos(double posX)
        {
            long ret = 0;
            bool posOK = false;
            while (!posOK)
            {
                //移动小药所在的行到针管的正上方
                ret = XMoveToDstPos(posX);
                if (0 == ret) { return 0; }
                //添加到位检测
                if ((WorkConfig.SolventEnableDetection == 1) && (nMotionCtrl.motionParam.nIOSet.iPausePort > 0))
                {
                    int v = 0;
                    ret = nMotionCtrl.ReadChannelInput(nMotionCtrl.motionParam.nIOSet.iPausePort, ref v);
                    if (1 == ret)
                    {
                        if (v == 1)
                        {
                            ButtonResult mbr = ButtonResult.Yes;//
                            Application.Current.Dispatcher.Invoke(
                            (Action)delegate ()
                            {
                                _dialogService.ShowDialog("AlertDialog", new DialogParameters($"message={"X轴移动到目标位置，没有感应到传感器，是否需要回零？"}"), r =>
                                {
                                    mbr = r.Result;
                                });
                            });
                            if (mbr == ButtonResult.Yes)
                            {
                                YMoveToDestPos(0);
                                nMotionCtrl.sAxisID = 0;
                                nMotionCtrl.SingleAxisHome();
                                posOK = false;
                            }
                            else
                            {
                                return 0;
                            }
                        }
                        else
                        {
                            posOK = true;
                        }
                    }
                    else
                    {
                        return 0;
                    }
                }
                else
                {
                    posOK = true;
                }
            }
            return 1;
        }

        private long MoveToPutSolventPos()
        {
            long ret = 0;
            nMotionCtrl.WorkPointID = 6;
            ret = nMotionCtrl.AbsMove(_X, WorkPoint.X_PutSolventPos);
            if (0 == ret)
            {
                return 0;
            }
            ret = nMotionCtrl.WaitForStop(); if (0 == ret) { return 0; }
            return 1;
        }

        #endregion X轴单周运动

        #region Y轴单周运动

        public long YMoveToZeroPos()
        {
            long ret = 0;
            //移动Y轴到安全高度
            LogHelper.Info("Y轴移动到零点位置！");
            ret = YMoveToDestPos(0);
            if (0 == ret) { return 0; }
            return 1;
        }

        //从溶媒袋拔针
        public long YMoveToSafe()
        {
            long ret = 0;
            LogHelper.Info("Y轴移动到安全位置！");
            ret = YMoveToDestPos(WorkPoint.Y_SafeHeight);
            if (0 == ret) { return 0; }
            return 1;
        }

        public long YMoveToDestPos(double dstPos)
        {
            long ret = 0;
            ret = nMotionCtrl.AbsMove(_Y, dstPos);
            if (0 == ret)
            {
                return 0;
            }
            ret = nMotionCtrl.WaitForStop(_Y);
            if (0 == ret) { return 0; }
            return 1;
        }

        #endregion Y轴单周运动

        #region Z轴单轴运动

        public long ZMoveToveDstPos(int AxisID, double pos)
        {
            long ret = 0;
            ret = nMotionCtrl.AbsMove(AxisID, pos);
            if (0 == ret)
            {
                return 0;
            }
            ret = nMotionCtrl.WaitForStop(); if (0 == ret) { return 0; }
            return 1;
        }

        #endregion Z轴单轴运动

        #endregion 单抽运动

        #region 设置Z轴速度

        private void SetAllZAxisSpeed(double[] speed)
        {
            for (int axisID = 2; axisID < nMotionCtrl.motionParam.motionCardParam.UsedAxisCount; axisID++)
            {
                int colID = axisID - _Z;
                nMotionCtrl.SetAxisSpeed(axisID, speed[colID]);
            }
        }

        //设置加工速度
        private double[] SetAllZAxisWorkSpeed()
        {
            double[] ASpeed = new double[MaxColPointCount];
            for (int axisID = 2; axisID < nMotionCtrl.motionParam.motionCardParam.UsedAxisCount; axisID++)
            {
                double speed = nMotionCtrl.GetWorkSpeedmm(axisID);
                ASpeed[axisID - _Z] = speed;
                nMotionCtrl.SetAxisSpeed(axisID, speed);
            }
            return ASpeed;
        }

        private long SetZAxisWorkSpeed(int AxisID)
        {
            double speed = nMotionCtrl.GetWorkSpeedmm(AxisID);
            int ret = nMotionCtrl.SetAxisSpeed(AxisID, speed);
            if (0 == ret) { return 0; }
            return 1;
        }

        #endregion 设置Z轴速度

        #region 所有Z轴同时运动,这个传入的数值是绝对位置点位

        //根据注射器的容积获取标志位
        //private  int[]  GetValidColByInjectorsHaveVolume()
        //{
        //    int[] validCol = new int[MaxColPointCount];
        //    for (int i = 0; i<StationColNum; i++)
        //    {
        //        if (mInjectors.injectors[i].InjectHadVolume>0)
        //        {
        //            validCol[i]=1;
        //        }
        //        else
        //        {
        //            validCol[i]=0;
        //        }
        //    }
        //    return validCol;
        //}

        #region 所有Z轴同时接收运动指令

        public long Abs_AllUsedZMoveToZero(int[] usedColFlag)
        {
            long ret = 0;
            int[] speed = ValueToArray(Convert.ToInt32(axisesSpeed[2].WorkSpeedScail));
            double[] pos = ValueToArray(0.0);
            ret = Abs_AllUsedZMoveToDstPos(usedColFlag, pos, speed);
            if (0 == ret) { return 0; }
            mInjectors.ResetInjector(usedColFlag);
            return 1;
        }

        private long Abs_AllUsedZMoveToDstPos(int[] usedColFlag, double[] pos, int[] percent)
        {
            long ret = 0;

            double[] bSpeed = SetAllZAxisSpeedByPercent(percent);
            for (int col = 0; col < StationColNum; col++)
            {
                //要冲配的行有药品，并且不是水针
                if (usedColFlag[col] == 1)
                {
                    int axisID = _Z + col;
                    ret = nMotionCtrl.NoEMG_AbsMove((axisID), bSpeed[col], pos[col]);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }
            ret = nMotionCtrl.WaitForStop();
            if (0 == ret) { return 0; }
            return 1;
        }

        private long Abs_AllUsedZMoveToDstPos(COneRowStation oneRow, int[] validCol, double pos, int[] percent)
        {
            long ret = 0;

            double[] bSpeed = SetAllZAxisSpeedByPercent(percent);
            for (int col = 0; col < StationColNum; col++)
            {
                //要冲配的行有药品，并且不是水针
                if ((oneRow.RowStations[col].UsedFlag == 1) && (validCol[col] == 1))
                {
                    int axisID = _Z + col;
                    ret = nMotionCtrl.NoEMG_AbsMove((axisID), bSpeed[col], pos);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }
            ret = nMotionCtrl.WaitForStop();
            if (0 == ret) { return 0; }
            return 1;
        }

        #endregion 所有Z轴同时接收运动指令

        public long VentAirFromInjector(int[] UsedFlag, double[] airML)
        {
            long ret = AllZMoveToZeroByInjectorAirVolume(UsedFlag, airML);
            if (0 == ret) { return 0; }
            mInjectors.ResetInjectorHadAirVolume(UsedFlag);
            return 1;
        }

        private long AllZMoveToZeroByInjectorAirVolume(int[] UsedFlag, double[] ML)
        {
            long ret = 0;
            int[] percent = ValueToArray(Convert.ToInt32(axisesSpeed[2].WorkSpeedScail));
            double[] bSpeed = SetAllZAxisSpeedByPercent(percent);
            for (int col = 0; col < StationColNum; col++)
            {
                //要冲配的行有药品，并且不是水针
                if ((UsedFlag[col] == 1) && (ML[col] > 0))
                {
                    int axisID = _Z + col;
                    ret = nMotionCtrl.NoEMG_AbsMove((axisID), bSpeed[col], 0);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }
            ret = nMotionCtrl.WaitForStop();
            if (0 == ret) { return 0; }
            return 1;
        }

        //回打溶媒
        public long Solvent_AllZMoveToZero(COneRowStation oneRow, int[] validCol, int[] percent)
        {
            return Abs_AllUsedZMoveToDstPos(oneRow, validCol, 0, percent);
        }

        #endregion 所有Z轴同时运动,这个传入的数值是绝对位置点位

        #region 反复抽液函数

        public long RepetitivePushAndPull(COneRowStation oneRow, int[] validCol, int loopIndex, int repullCount, double[] volume, int[] inSpeed, int[] outSpeed, double waitTime)
        {
            long ret = 0;
            bool isZero = AllValueIsZero(volume);
            if (true == isZero)
            {
                return 1;
            }
            if ((repullCount > 0))
            {
                //Y轴移动到抽液最低位
                ret = Bottle_YMoveToPumpingLow(oneRow, loopIndex);
                if (0 == ret) { return 0; }
                //添加判断，打入的空气量需要几次
                ret = PushAndPull(validCol, repullCount, volume, outSpeed, inSpeed, waitTime);
                if (0 == ret) { return 0; }
            }
            return 1;
        }

        private long PushAndPull(int[] iValidCol, int repullCount, double[] volume, int[] outSpeed, int[] inSpeed, double waitTime)
        {
            long ret = 0;
            if (repullCount > 0)
            {
                //这个地方需要添加根据注射器的剩余容积，来判断反复抽液的容积是否超出了注射器的剩余容积？？？？？？？？？？
                double[] validVolume = GetInjectorCanUsedVolume(volume, iValidCol);
                SetRunState("反复抽液");
                for (int loop = 0; loop < repullCount; loop++)
                {
                    Thread.Sleep(Convert.ToInt32(waitTime * 1000));
                    ret = Out_AllZWithSpecifiedPercent(iValidCol, validVolume, outSpeed);
                    if (0 == ret) { return 0; }
                    ret = In_AllZWithSpecifiedPercent(iValidCol, validVolume, inSpeed);
                    if (0 == ret) { return 0; }
                }
            }
            return 1;
        }

        #endregion 反复抽液函数

        #region 从西林瓶抽出一定的容积，这里面传入额数值是药运行的相对位置

        #region 所有Z轴按加工速度运行

        public long Out_ALLZWithWorkSpeed(int[] usedFlag, double[] allZml)
        {
            long ret = 0;
            int percent = Convert.ToInt32(axisesSpeed[2].WorkSpeedScail);
            int[] percents = ValueToArray(percent);
            ret = Out_AllZWithSpecifiedPercent(usedFlag, allZml, percents);
            if (0 == ret) { return 0; }
            return 1;
        }

        #endregion 所有Z轴按加工速度运行

        public long Out_AllZWithSpecifiedPercent(int[] usedFlag, double[] allZml, int[] percent)
        {
            return OutOrIn_AllUsedZ(usedFlag, allZml, percent, ZOUT);
        }

        //所有的Z轴按加工速度运行

        #endregion 从西林瓶抽出一定的容积，这里面传入额数值是药运行的相对位置

        #region all z 轴注入一定的容积

        private long In_ALLZWithWorkSpeed(int[] usedFlag, double[] allZml)
        {
            long ret = 0;
            int[] percent = ValueToArray(Convert.ToInt32(axisesSpeed[2].WorkSpeedScail));
            ret = In_AllZWithSpecifiedPercent(usedFlag, allZml, percent);
            if (0 == ret) { return 0; }
            return 1;
        }

        public long In_AllZWithSpecifiedPercent(int[] usedFlag, double[] allZml, int[] percent)
        {
            return OutOrIn_AllUsedZ(usedFlag, allZml, percent, ZIN);
        }

        #endregion all z 轴注入一定的容积

        #region ALL Z轴，抽出或者注入函数

        public static int ZOUT = 1;
        public static int ZIN = -1;

        private long OutOrIn_AllUsedZ(int[] usedFlag, double[] allZml, int[] percent, int OutOrIn = 1)
        {
            long ret = 0;
            double[] bSpeed = GetAllZAixsSpeedByPercent(percent);
            ret = OutOrIn_AllUsedZ(usedFlag, allZml, bSpeed, OutOrIn);
            if (0 == ret) { return 0; }
            return 1;
        }

        private long OutOrIn_AllUsedZ(int[] usedFlag, double[] allZml, double[] allZSpeed, int OutOrIn = 1)
        {
            long ret = 0;
            if (true == AllValueIsZero(allZml))
            {
                //所有的值都为零
                return 1;
            }
            SetAllZAxisSpeed(allZSpeed);
            for (short colID = 0; colID < StationColNum; colID++)
            {
                if (usedFlag[colID] == 1)
                {
                    int AxisID = (_Z + colID);
                    if ((allZml[colID] == 0))
                    {
                        //如果，抽出容量为0，轴不动作
                        continue;
                    }
                    ret = OutOrIn_Z(AxisID, allZml[colID], allZSpeed[colID], OutOrIn);//冲入液体
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }
            ret = nMotionCtrl.WaitForStop();
            if (0 == ret) { return 0; }
            return 1;
        }

        #endregion ALL Z轴，抽出或者注入函数

        #region 单抽抽液运动

        private long Out_ZWithWorkSpeed(int AxisID, double ml)
        {
            double speed = nMotionCtrl.GetWorkSpeedmm(AxisID);
            return Out_Z(AxisID, ml, speed);
        }

        public long Out_ZWithSpecifiedPercent(int AxisID, double ml, int percent)
        {
            double speed = SpeedPercentToMM(AxisID, percent);
            long ret = Out_Z(AxisID, ml, speed);
            if (0 == ret) { return 0; }
            return 1;
        }

        public long Out_Z(int AxisID, double ml, double speed)
        {
            return OutOrIn_Z(AxisID, ml, speed, ZOUT);
        }

        public long In_Z(int AxisID, double ml, double speed)
        {
            return OutOrIn_Z(AxisID, ml, speed, ZIN);
        }

        private long OutOrIn_Z(int AxisID, double ml, double speed, int OutOrIn = 1)
        {
            if (ml == 0)
            {
                return 1;
            }
            long ret = 0;
            double nDis = MLTomm(ml);
            double currentPos = 0;
            //currentPos =nMotionCtrl.AbsCurrentPos_mm[AxisID];
            nMotionCtrl.GetPos(AxisID, ref currentPos);
            double absPos = 0;
            if (1 == OutOrIn)
            {
                absPos = currentPos + nDis;
            }
            else
            {
                absPos = currentPos - nDis;
            }
            ret = nMotionCtrl.NoEMG_AbsMove(AxisID, speed, absPos);
            if (0 == ret) { return 0; }
            return 1;
        }

        #endregion 单抽抽液运动

        #region 插拔针 函数

        public double GetFlushLowPos(COneRowStation oneRow, int dmLoopIndex = 0)
        {
            double[] bottleThikness = oneRow.GetBOTTLE_THICKNESS();
            double[] FlushOffsetHeight = oneRow.GetFlushOffsetHeight(dmLoopIndex);
            double maxbottleThikness = GetMaxValue(bottleThikness);
            double maxFlushOffsetHeight = GetMaxValue(FlushOffsetHeight);
            double flushLowPos = WorkPoint.Y_FlushHeightLow + maxbottleThikness + maxFlushOffsetHeight;
            if (flushLowPos < WorkPoint.Y_PumpHeightLow)
            {
                flushLowPos = WorkPoint.Y_PumpHeightLow;
            }
            if (flushLowPos > WorkPoint.Y_FlushHeightHight)
            {
                flushLowPos = WorkPoint.Y_FlushHeightHight;
            }
            return flushLowPos;
        }

        public double GetOutLowOffset(COneRowStation oneRow, int dmLoopIndex = 0)
        {
            double[] bottleThikness = oneRow.GetBOTTLE_THICKNESS();
            double[] OutLowOffset = oneRow.GetFlushOutLowOffset(dmLoopIndex);
            double maxbottleThikness = GetMaxValue(bottleThikness);
            double maxFlushOffsetHeight = GetMaxValue(OutLowOffset);
            double flushLowPos = WorkPoint.Y_PumpHeightLow + maxbottleThikness + maxFlushOffsetHeight;
            if (flushLowPos < WorkPoint.Y_PumpHeightLow)
            {
                flushLowPos = WorkPoint.Y_PumpHeightLow;
            }
            if (flushLowPos > WorkPoint.Y_FlushHeightHight)
            {
                flushLowPos = WorkPoint.Y_FlushHeightHight;
            }
            return flushLowPos;
        }

        public long Bottle_YMoveToSafe1(COneRowStation oneRow)
        {
            LogHelper.Info("Y轴移动到安全高度");
            return YMoveToDestPos(WorkPoint.Y_SafeHeight);
        }

        public long Bottle_YPullOutToSafe(COneRowStation oneRow)
        {
            LogHelper.Info("Y轴拔针移动到安全高度");
            return Bottle_YPullOut(oneRow, WorkPoint.Y_SafeHeight);
        }

        public long Bottle_YPullOutToStart(COneRowStation oneRow)
        {
            long ret = 0;
            ret = Bottle_YPullOut(oneRow, WorkPoint.Y_BottleStartPunctureHeight);
            if (0 == ret)
            {
                return 0;
            }
            return 1;
        }

        //Y轴移动到冲刷位置高
        public long Bottle_YMoveToFlushHight(COneRowStation oneRow)
        {
            long ret = 0;
            if (true == NeedleInBottle)
            {
                ret = YMoveToDestPos(WorkPoint.Y_FlushHeightHight);
            }
            else
            {
                ret = Bottle_YPlugIn(oneRow, WorkPoint.Y_FlushHeightHight);
            }
            if (0 == ret) { return 0; }
            return 1;
        }

        public long Bottle_YPlugInToFlushHight(COneRowStation oneRow)
        {
            long ret = 0;
            ret = Bottle_YPlugIn(oneRow, WorkPoint.Y_FlushHeightHight);
            if (0 == ret) { return 0; }
            return 1;
        }

        public long Bottle_YMoveToFlushLow(COneRowStation oneRow, int dmLoopIndex)
        {
            long ret = 0;
            double flushLowPos = GetFlushLowPos(oneRow, dmLoopIndex);
            if (true == NeedleInBottle)
            {
                ret = YMoveToDestPos(flushLowPos);
            }
            else
            {
                ret = Bottle_YPlugIn(oneRow, flushLowPos);
            }
            if (0 == ret) { return 0; }
            return 1;
        }

        public long Bottle_YMoveToPumpingLow(COneRowStation oneRow, int dmLoopIndex)
        {
            long ret = 0;
            double lowPos = GetOutLowOffset(oneRow, dmLoopIndex);
            if (true == NeedleInBottle)
            {
                ret = YMoveToDestPos(lowPos);
            }
            else
            {
                ret = Bottle_YPlugIn(oneRow, lowPos);
            }
            if (0 == ret) { return 0; }
            return 1;
        }
        //移动到冲刷抽液高度
        public long Bottle_YMoveToFlushPumpingHight(COneRowStation oneRow, int dmLoopIndex)
        {
            long ret = 0;
            double[] bottleThikness = oneRow.GetBOTTLE_THICKNESS();
            double[] flushOutHeightOffset=oneRow.Get_FlushOutHeightOffset(dmLoopIndex);

            double maxbottleThikness = GetMaxValue(bottleThikness);
            double maxFlushOutHeightOffset=GetMaxValue(flushOutHeightOffset);
            double flushPumpPos = WorkPoint.Y_PumpHeightHight + maxbottleThikness+maxFlushOutHeightOffset;
            if (true == NeedleInBottle)
            {
                ret = YMoveToDestPos(flushPumpPos);
            }
            else
            {
                ret = Bottle_YPlugIn(oneRow, flushPumpPos);
            }
            return ret;
        }

        private long Bottle_YPlugIn(COneRowStation oneRow, double dstPos)
        {
            long ret = 0;
            //只要有一个启用了穿刺慢速度，所有轴都按穿刺慢速度执行
            int[] dropCrumb = oneRow.GetDropCrumb();
            int[] PunctureSlowSpeed = oneRow.GetPunctureSlowSpeed();//获取穿刺慢速度
            string str = ArrayToString(PunctureSlowSpeed);
            LogHelper.Info("读取到的穿刺慢速度=" + str);
            int minPunctureSlowSpeed = GetMinValue(PunctureSlowSpeed);
            LogHelper.Info("穿刺慢速度=" + minPunctureSlowSpeed.ToString());
            bool enableFlag = false;
            for (int i = 0; i < StationColNum; i++)
            {
                if ((dropCrumb[i] == 1) || (dropCrumb[i] == 3))
                {
                    enableFlag = true;
                    break;
                }
            }

            double EndPos = WorkPoint.Y_FlushHeightHight;
            double startPos = WorkPoint.Y_BottleStartPunctureHeight;
            if (true == enableFlag)
            {
                //开启慢速插针，插针掉屑，插拔针掉屑
                double curpos = nMotionCtrl.AbsDestPos_mm[_Y];
                nMotionCtrl.GetPos(_Y, ref curpos);

                if (curpos > startPos)
                {
                    //说明注射器针尖在西林瓶内，则不用慢穿刺，直接快速运行就行
                    LogHelper.Info("针尖在西林瓶内，无需慢速运行！当前位置=" + curpos.ToString());
                    ret = YMoveToDestPos(dstPos);
                    if (0 == ret) { return 0; }
                }
                else
                {
                    LogHelper.Info("开始慢速穿刺西林瓶");
                    //1.移动到穿刺起始位置
                    LogHelper.Info("快速度：移动到穿刺起始位置" + WorkPoint.Y_BottleStartPunctureHeight.ToString());
                    ret = YMoveToDestPos(WorkPoint.Y_BottleStartPunctureHeight);
                    if (0 == ret) { return 0; }
                    //以慢速度，移动到穿刺结束位置
                    LogHelper.Info("慢速度:移动到穿刺结束位置" + WorkPoint.Y_BottleEndPunctureHeight.ToString());
                    double slowSpeed = SpeedPercentToMM(_Y, minPunctureSlowSpeed);
                    ret = nMotionCtrl.AbsMove(_Y, slowSpeed, WorkPoint.Y_BottleEndPunctureHeight);
                    if (0 == ret) { return 0; }
                    ret = nMotionCtrl.WaitForStop(_Y);
                    if (0 == ret) { return 0; }
                    ret = YMoveToDestPos(EndPos); if (0 == ret) { return 0; }
                    LogHelper.Info("快速度：移动到目标位置=" + dstPos.ToString());
                    ret = YMoveToDestPos(dstPos); if (0 == ret) { return 0; }
                    LogHelper.Info("慢速穿刺西林瓶动作结束！");
                }
            }
            else
            {
                ret = YMoveToDestPos(EndPos);
                if (0 == ret) { return 0; }
                //不掉屑，或拔针掉屑，插针不掉屑
                ret = YMoveToDestPos(dstPos);
                if (0 == ret) { return 0; }
            }
            NeedleInBottle = true;
            return 1;
        }

        //拔针到指定位置
        private long Bottle_YPullOut(COneRowStation oneRow, double dstPos)
        {
            long ret = 0;
            //只要有一个启用了穿刺慢速度，所有轴都按穿刺慢速度执行
            int[] dropCrumb = oneRow.GetDropCrumb();
            int[] PunctureSlowSpeed = oneRow.GetPunctureSlowSpeed();//获取穿刺慢速度
            int minPunctureSlowSpeed = GetMinValue(PunctureSlowSpeed);
            bool enableFlag = false;
            for (int i = 0; i < StationColNum; i++)
            {
                if ((dropCrumb[i] == 2) || (dropCrumb[i] == 3))
                {
                    enableFlag = true;
                    break;
                }
            }
            if (true == enableFlag)
            {
                //拔针掉屑，插拔针掉屑
                double curpos = nMotionCtrl.AbsDestPos_mm[_Y];
                nMotionCtrl.GetPos(_Y, ref curpos);
                double startPos = WorkPoint.Y_BottleStartPunctureHeight;
                if (curpos > startPos)
                {
                    LogHelper.Info("慢速拔针：");
                    //注射器针尖在西林瓶内
                    //1.移动到穿刺结束位置
                    LogHelper.Info("快速度：移动到穿刺结束位置=" + WorkPoint.Y_BottleEndPunctureHeight.ToString());
                    ret = YMoveToDestPos(WorkPoint.Y_BottleEndPunctureHeight);
                    if (0 == ret) { return 0; }
                    //2.慢速移动到起始位置
                    LogHelper.Info("慢速度：移动到起始位置=" + WorkPoint.Y_BottleStartPunctureHeight.ToString());
                    double slowSpeed = SpeedPercentToMM(_Y, minPunctureSlowSpeed);
                    ret = nMotionCtrl.AbsMove(_Y, slowSpeed, WorkPoint.Y_BottleStartPunctureHeight);
                    if (0 == ret) { return 0; }
                    ret = nMotionCtrl.WaitForStop(_Y);
                    if (0 == ret) { return 0; }
                    //3.移动到目标位置
                    LogHelper.Info("快速度：移动到目标位置=" + dstPos.ToString());
                    ret = YMoveToDestPos(dstPos);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
                else
                {
                    //注射器已经拔出西林瓶
                    LogHelper.Info("");
                    ret = YMoveToDestPos(dstPos);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }
            else
            {
                ret = YMoveToDestPos(dstPos);
                if (0 == ret)
                {
                    return 0;
                }
            }
            NeedleInBottle = false;
            return 1;
        }

        public long Solvent_Plugin(DTO_adi_dic_drug usedSolvent)
        {
            long ret = 0;
            double dstPos = 0;
            if (usedSolvent.SOLVENT_FLAG != 2)
            {
                //普通溶媒，从溶媒里面抽液
                dstPos = WorkPoint.Y_SolventHeight;
            }
            else
            {
                //专用溶媒，从西林瓶位置抽取溶媒
                dstPos = WorkPoint.Y_PumpHeightLow;
                ret = Solvent_YMoveToDstPos(usedSolvent, WorkPoint.Y_PumpHeightHight);
                if (0 == ret)
                {
                    return 0;
                }
            }
            ret = Solvent_YMoveToDstPos(usedSolvent, dstPos);
            if (0 == ret) { return 0; }
            return 1;
        }

        public long Solvent_PlugOutSafe(DTO_adi_dic_drug usedSolvent)
        {
            long ret = 0;
            ret = Solvent_YMoveToDstPos(usedSolvent, WorkPoint.Y_SafeHeight);
            if (0 == ret) { return 0; }
            return 1;
        }

        //移动到穿刺起始高度
        public long Solvent_PullOutStart(DTO_adi_dic_drug usedSolvent)
        {
            long ret = 0;
            ret = Solvent_YMoveToDstPos(usedSolvent, WorkPoint.Y_SolventStartPunctureHeight);
            if (0 == ret) { return 0; }
            return 1;
        }

        public long Solvent_YMoveToDstPos(DTO_adi_dic_drug usedSolvent, double dstPos)
        {
            long ret = 0;
            double cupos = nMotionCtrl.AbsDestPos_mm[_Y];
            double startPos = WorkPoint.Y_SolventStartPunctureHeight;
            if (dstPos <= startPos)
            {
                //目标位置小于穿刺其实位置
                ret = Solvent_PullOutToDstPos(usedSolvent, dstPos);
            }
            else
            {
                ret = Solvent_PluginToDstPos(usedSolvent, dstPos);
            }
            return ret;
        }

        private long Solvent_PluginToDstPos(DTO_adi_dic_drug usedSolvent, double dstPos)
        {
            long ret = 0;
            if ((usedSolvent.DropCrumb == 1) || (usedSolvent.DropCrumb == 3))
            {
                //1.穿刺掉屑，3.插拔掉屑
                double cupos = nMotionCtrl.AbsDestPos_mm[_Y];
                double startPos = WorkPoint.Y_SolventStartPunctureHeight;
                if (cupos > startPos)
                {
                    //说明针尖已经在溶媒袋内
                    ret = YMoveToDestPos(dstPos); if (0 == ret) { return 0; }
                }
                else
                {
                    LogHelper.Info("开始慢速穿刺溶媒袋！");
                    //先移动到穿刺起始位置
                    ret = YMoveToDestPos(WorkPoint.Y_SolventStartPunctureHeight); if (0 == ret) { return 0; }
                    //慢速插入
                    double pos = WorkPoint.Y_SolventStartPunctureHeight + 10;
                    double slowSpeed = SpeedPercentToMM(_Y, usedSolvent.PunctureSlowSpeed);
                    ret = nMotionCtrl.AbsMove(_Y, slowSpeed, pos);
                    if (0 == ret) { return 0; }
                    ret = nMotionCtrl.WaitForStop(_Y);
                    if (0 == ret) { return 0; }
                    //移动到最终位置
                    ret = YMoveToDestPos(dstPos);
                    if (0 == ret) { return 0; }
                }
            }
            else
            {
                ret = YMoveToDestPos(dstPos);
                if (0 == ret) { return 0; }
            }
            return 1;
        }

        private long Solvent_PullOutToDstPos(DTO_adi_dic_drug usedSolvent, double dstPos)
        {
            long ret = 0;
            if ((usedSolvent.DropCrumb == 2) || (usedSolvent.DropCrumb == 3))
            {
                //2.拔针掉屑，3.插拔掉屑
                //先移动到穿刺结束位置
                double cupos = nMotionCtrl.AbsDestPos_mm[_Y];
                double startPos = WorkPoint.Y_SolventStartPunctureHeight;
                if (cupos > startPos)
                {
                    //说明针尖不在溶媒袋内
                    double pos = WorkPoint.Y_SolventStartPunctureHeight + 10;
                    ret = YMoveToDestPos(pos); if (0 == ret) { return 0; }
                    //已慢速度移动到穿刺起始位置
                    double slowSpeed = SpeedPercentToMM(_Y, usedSolvent.PunctureSlowSpeed);
                    ret = nMotionCtrl.AbsMove(_Y, slowSpeed, WorkPoint.Y_SolventStartPunctureHeight + 5);
                    if (0 == ret)
                    {
                        return 0;
                    }
                    ret = nMotionCtrl.WaitForStop(_Y); if (0 == ret) { return 0; }
                    //移动到最终位置
                    ret = YMoveToDestPos(dstPos); if (0 == ret) { return 0; }
                }
                else
                {
                    ret = YMoveToDestPos(dstPos); if (0 == ret) { return 0; }
                }
            }
            else
            {
                ret = YMoveToDestPos(dstPos); if (0 == ret) { return 0; }
            }

            return 1;
        }

        #endregion 插拔针 函数

        #region 获取容积函数

        //根据注射器的剩余容积，获取注射器可以抽取的容积
        //判断注射器内是否还有剩余的容积
        public bool InjectorCanInVolume(COneRowStation oneRow, int[] iValidCol)
        {
            int[] usedFlag = oneRow.GetUsedFlag();
            int[] validCol = ANDFlag(usedFlag, iValidCol);
            double[] InjectorResidualVolume = mInjectors.GetInjectResidualVolume();//  oneRow.GetInjectResidualVolume();//获取注射器的剩余容积
            return InjectorCanInVolume(validCol, InjectorResidualVolume);
        }

        //判断是不是所有的注射器都没有可用容积
        //false:所有注射器都没有可用容积，true:有注射器有可用容积
        private bool InjectorCanInVolume(int[] validCol, double[] InjectorResidualVolume)
        {
            bool CanIn = false;
            for (int i = 0; i < StationColNum; i++)
            {
                if (validCol[i] == 1)
                {
                    if (InjectorResidualVolume[i] <= 0)
                    {
                        SetRunState("注射器" + (i + 1).ToString() + "内没有剩余的容积", LogLevel.Warning);
                    }
                    else
                    {
                        CanIn = true;
                    }
                }
            }
            return CanIn;
        }

        //反复抽液的时候用

        //获取注射器可以使用的容积
        private double[] GetInjectorCanUsedVolume(COneRowStation oneRow, int[] iValidCol, double[] NeedUsedVolume)
        {
            int[] validCol = oneRow.ANDFlag(iValidCol);
            return GetInjectorCanUsedVolume(NeedUsedVolume, validCol);
        }

        //获取注射器可以使用的容积
        public double[] GetInjectorCanUsedVolume(double[] NeedUsedVolume, int[] iValidCol)
        {
            double[] InjectResidualVolume = mInjectors.GetInjectResidualVolume();// 获取注射器剩余容积
            return GetInjectorCanUsedVolume(InjectResidualVolume, NeedUsedVolume, iValidCol);//获取实际用到的容积
        }

        //获取注射器可以实际使用的体积
        private double[] GetInjectorCanUsedVolume(double[] InjectResidualVolume, double[] NeedInVolume, int[] validCol)
        {
            double[] dml = new double[MaxColPointCount];
            for (int colID = 0; colID < StationColNum; colID++)
            {
                double ml = 0;
                if (validCol[colID] == 1)
                {
                    if (InjectResidualVolume[colID] < NeedInVolume[colID])
                    {
                        //注射器的剩余容积，小于需要的容积
                        if (InjectResidualVolume[colID] <= 0)
                        {
                            //注射器剩余容积为0，
                            ml = 0;
                            SetRunState("注射器" + (colID + 1).ToString() + "内没有剩余的容积", LogLevel.Warning);
                        }
                        else
                        {
                            //注射器剩余多少，就使用多少
                            ml = InjectResidualVolume[colID];
                        }
                    }
                    else
                    {
                        //注射器剩余容积大于使用容积
                        ml = NeedInVolume[colID];
                    }
                    dml[colID] = ml;
                }
                else
                {
                    dml[colID] = 0;
                }
            }
            return dml;
        }

        public int[] ANDFlag(int[] validFlag1, int[] validFlag2)
        {
            int[] validFlag = new int[MaxColPointCount];
            for (int i = 0; i < StationColNum; i++)
            {
                if ((validFlag1[i] == 1) && (validFlag2[i] == 1))
                {
                    validFlag[i] = 1;
                }
                else
                {
                    validFlag[i] = 0;
                }
            }
            return validFlag;
        }

        //获取抽溶媒的体积，整只，和非整只抽取的容积不一样
        private double[] GetOutSolventVolume(COneRowStation oneRow, int loopIndex)
        {
            double[] OutMl = new double[MaxColPointCount];
            for (int col = 0; col < StationColNum; col++)
            {
                if (oneRow.RowStations[col].UsedFlag == 0)
                {
                    OutMl[col] = 0;
                    continue;
                }
                if (loopIndex == 0)
                {
                    if (oneRow.UsedDrug.SOLVENT_FLAG == 0)
                    {
                        //普通溶媒
                        if ((oneRow.RowStations[col].FeiZhengZhiMode == 1))
                        {
                            //非整只模式:水针是计算出来的实际体积，专用溶媒，抽出的是冲刷体积

                            OutMl[col] = Convert.ToDouble(oneRow.RowStations[col].UsedDrug.flush_Groups[oneRow.UsedDrug.FlushGroupIndex].flush_Params[0].IN_VOLUME);
                        }
                        else
                        {
                            //整只抽取的溶媒
                            OutMl[col] = Convert.ToDouble(oneRow.RowStations[col].UsedDrug.flush_Groups[oneRow.UsedDrug.FlushGroupIndex].flush_Params[loopIndex].SolventVolume);
                        }
                    }
                    else if (oneRow.UsedDrug.SOLVENT_FLAG == 2)
                    {
                        //专用溶媒:不管是不是整只，都要将专用溶媒全部抽完
                        OutMl[col] = Convert.ToDouble(oneRow.RowStations[col].UsedDrug.flush_Groups[oneRow.UsedDrug.FlushGroupIndex].flush_Params[0].IN_VOLUME);
                    }
                    else
                    {
                        //MessageBox.Show("溶媒属性设置有问题，无法进行配药，请确定药品属性！");
                        string str = "溶媒属性设置有问题，无法进行配药，请确定药品属性！";
                        Application.Current.Dispatcher.Invoke(
                        (Action)delegate ()
                        {
                            _dialogService.ShowDialog("WarningDialog", new DialogParameters($"message={str}"), null);
                        });

                        OutMl[col] = 0;
                    }
                }
                else
                {
                    if (oneRow.RowStations[col].FeiZhengZhiMode == 1)
                    {
                        //非整只模式，抽取的溶媒
                        OutMl[col] = 0;
                    }
                    else
                    {
                        //整只抽取的溶媒
                        OutMl[col] = Convert.ToDouble(oneRow.RowStations[col].UsedDrug.flush_Groups[oneRow.UsedDrug.FlushGroupIndex].flush_Params[loopIndex].SolventVolume);
                    }
                }
            }
            return OutMl;
        }

        //计算非整只模式下，需要回打，或多抽的容积
        public double[] GetBackToBottleVolume(COneRowStation oneRow, int[] validCol)
        {
            double[] dml = new double[MaxColPointCount];
            for (int col = 0; col < StationColNum; col++)
            {
                if (validCol[col] == 1)
                {
                    if (oneRow.RowStations[col].FeiZhengZhiMode == 1)
                    {
                        //非整只
                        double[] fzzInVolume = oneRow.GetFlushInVolume(0);
                        dml[col] = fzzInVolume[col] + fzzInVolume[col] * oneRow.RowStations[col].UsedDrug.CoefficientOfExpansion - oneRow.RowStations[col].fzz_OutVolume;
                    }
                    else
                    {
                        //整只模式
                        dml[col] = 0;
                    }
                }
            }
            return dml;
        }

        //获取回抽多抽体积
        public double[] GetPumpBackOutVolume(COneRowStation oneRow, int[] validCol, int dmLoopIndex)
        {
            double[] PumpbackVolumes = oneRow.GetPumpbackVolume(dmLoopIndex);
            double[] dml = GetInjectorCanUsedVolume(oneRow, validCol, PumpbackVolumes);
            return dml;
        }

        //获取多抽空气体积
        public double[] GetAdditionalPullOutAirVolume(COneRowStation oneRow, int[] validCol, int dmLoopIndex)
        {
            //非整只不支持多抽空气
            double[] additionalAir = oneRow.GetAdditionalOutAirVolume(dmLoopIndex);//多抽空气体积
            double[] validAir = GetValidValue(additionalAir, validCol);
            double[] canUsedML = GetInjectorCanUsedVolume(validAir, validCol);
            return canUsedML;
        }

        //获取多抽液体体积
        public double[] GetAdditionalPullOutLiquidVolume(COneRowStation oneRow, int[] validCol, int dmLoopIndex, bool[] IsLastBottle)
        {
            double[] validML = new double[MaxColPointCount];
            double[] additionalML = new double[MaxColPointCount];
            double[] ADDITIONAL_PUMPING = oneRow.GetADDITIONAL_PUMPING(dmLoopIndex);//多抽体积
            int[] DrugCountOfLoopFlush = oneRow.GetDrugCountOfLoopFlush(dmLoopIndex);//一次配几支药
            double[] LastBottleAdditionOutVolume = oneRow.GetLastBottleAdditionOutVolume(dmLoopIndex);//最后一瓶多抽体积

            if ((true == AllValueIsZero(ADDITIONAL_PUMPING)) && (true == AllValueIsZero(LastBottleAdditionOutVolume)))
            {
                //多抽体积和最后一瓶多抽体积都为0
                return additionalML;
            }
            for (int i = 0; i < StationColNum; i++)
            {
                //非整只不支持多抽
                if ((oneRow.RowStations[i].UsedFlag == 1) && (oneRow.RowStations[i].FeiZhengZhiMode == 0))
                {
                    if ((DrugCountOfLoopFlush[i] > 1))
                    {
                        //在抽一次溶媒，配两支药，或抽一次溶媒配4只药的情况下，最后一瓶多抽体积才有效
                        if (true == IsLastBottle[i])
                        {
                            additionalML[i] = ADDITIONAL_PUMPING[i] + LastBottleAdditionOutVolume[i];
                        }
                        else
                        {
                            additionalML[i] = ADDITIONAL_PUMPING[i];
                        }
                    }
                    else
                    {
                        additionalML[i] = ADDITIONAL_PUMPING[i];
                    }
                }
                else
                {
                    //没有启用，或是非整只
                    additionalML[i] = 0;
                }
            }

            validML = GetValidValue(additionalML, validCol);
            double[] canUsedML = GetInjectorCanUsedVolume(validML, validCol);
            return canUsedML;
        }

        #endregion 获取容积函数

        #region 设置使用标志位

        public bool SZ_JudgeWetherNeedRebackSolvent(COneRowStation oneRow)
        {
            for (int i = 0; i < DeviceConfig.StationColNum; i++)
            {
                if ((oneRow.RowStations[i].UsedFlag == 1) && (mInjectors.injectors[i].InjectHadVolume > 0))
                {
                    //有启用的站
                    return true;
                }
            }
            return false;
        }

        //获取站台启用标志位
        private int[] GetUsedFlag(COneRowStation oneRow)
        {
            return oneRow.GetUsedFlag();
        }

        #endregion 设置使用标志位
    }
}